package org.mparts.server.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.mparts.server.EMF;
import org.mparts.server.bean.NewsLoadResultBean;
import org.mparts.server.bean.PartitemLoadResultBean;
import org.mparts.server.bean.PartitemPagingLoadResultBean;
import org.mparts.server.domain.Auto;
import org.mparts.server.domain.Engine;
import org.mparts.server.domain.Model;
import org.mparts.server.domain.News;
import org.mparts.server.domain.Partgroup;
import org.mparts.server.domain.Partitem;
import org.mparts.server.utils.CacheUtils;
import org.mparts.server.utils.Paginate;
import org.mparts.server.utils.PersistUtils;

import com.google.gwt.core.shared.GWT;
import com.sencha.gxt.data.shared.SortInfoBean;
import com.sencha.gxt.data.shared.loader.FilterConfigBean;

public class MpartService {

	private static Logger log = Logger.getLogger(MpartService.class.getName());
	

	public MpartService() {
	}

	@SuppressWarnings("unchecked")
	public List<Partgroup> findAllPartgroups() {
		List<Partgroup> partGroupList = null;
		try {
			partGroupList = (List<Partgroup>) CacheUtils
					.getCacheData(CacheUtils.GROUPS_LIST_KEY);
			if (partGroupList == null) {
				EntityManager mgr = PersistUtils.getEntityManager();
				Query q = mgr.createQuery(
						"select x from Partgroup x order by name ASC",
						Partgroup.class);
				partGroupList = q.getResultList();
				CacheUtils.setCacheData(CacheUtils.GROUPS_LIST_KEY,
						partGroupList);
			}
			//		} finally {
//			mgr.close();
		} catch (Exception e) {
			log.severe("Failed load partgroups list");
		}

		return partGroupList;

	}

	@SuppressWarnings("unchecked")
	public List<Engine> findAllEngines() {
		List<Engine> engineList = null;
		try {
			engineList = (List<Engine>) CacheUtils
					.getCacheData(CacheUtils.ENGINE_LIST_KEY);
			if (engineList == null) {
				EntityManager mgr = PersistUtils.getEntityManager();
				Query q = mgr.createQuery(
						"select x from Engine x order by name ASC",
						Engine.class);
				engineList = q.getResultList();
				CacheUtils.setCacheData(CacheUtils.ENGINE_LIST_KEY,
						engineList);
			}
			//		} finally {
//			mgr.close();
		} catch (Exception e) {
			log.severe("Failed load engines list");
		}

		return engineList;

	}
	public List<Partitem> findAllPartitems() {
		EntityManager mgr = PersistUtils.getEntityManager();
		List<Partitem> partItemList = null;
		// try {
		TypedQuery<Partitem> q = mgr.createQuery("select x from Partitem x",
				Partitem.class);
		partItemList = q.getResultList();
		// } finally {
		// mgr.close();
		// }

		return partItemList;

	}

	public PartitemLoadResultBean findPartitems(String criteria) {
		EntityManager mgr = PersistUtils.getEntityManager();
		List<Partitem> partItemList = null;
		// try {
		CriteriaBuilder cb = mgr.getCriteriaBuilder();
		CriteriaQuery<Partitem> c = cb.createQuery(Partitem.class);
		Root<Partitem> r = c.from(Partitem.class);

		if (criteria != null && criteria.length() > 0) {
			List<Predicate> pList = new ArrayList<Predicate>();
			String criteriaLowerCase = criteria.toLowerCase();
			pList.add(cb.or(cb.like(cb.lower(r.<String> get("autoName")), "%"
					+ criteriaLowerCase + "%")));
			pList.add(cb.or(cb.like(cb.lower(r.<String> get("modelName")), "%"
					+ criteriaLowerCase + "%")));
			pList.add(cb.or(cb.like(cb.lower(r.<String> get("note")), "%"
					+ criteriaLowerCase + "%")));
			pList.add(cb.or(cb.like(cb.lower(r.<String> get("manCode")), "%"
					+ criteriaLowerCase + "%")));
			pList.add(cb.or(cb.like(cb.lower(r.<String> get("vin")), "%"
					+ criteriaLowerCase + "%")));
			pList.add(cb.or(cb.like(cb.lower(r.<String> get("engine")), "%"
					+ criteriaLowerCase + "%")));

			c.where(cb.or(pList.toArray(new Predicate[] {})));
		}

		TypedQuery<Partitem> q = mgr.createQuery(c);
		partItemList = q.getResultList();
		// } finally {
		// mgr.close();
		// }
		PartitemLoadResultBean bean = new PartitemLoadResultBean();
		bean.setData(partItemList);

		return bean;

	}

	// public PartitemPagingLoadResultBean findPartitems(int offset, int limit,
	// List<SortInfoBean> sortInfo, List<FilterConfigBean> filterConfig, String
	// criteria) {
	// EntityManager mgr = PersistUtils.getEntityManager();
	// // try {
	// Predicate orPredicate = null;
	//
	// if (criteria != null && criteria.length() > 0) {
	// CriteriaBuilder cb = mgr.getCriteriaBuilder();
	// CriteriaQuery<Partitem> c = cb.createQuery(Partitem.class);
	// Root<Partitem> r = c.from(Partitem.class);
	//
	// List<Predicate> pList = new ArrayList<Predicate>();
	// String criteriaLowerCase = criteria.toLowerCase();
	// pList.add(cb.or(cb.like(cb.lower(r.<String> get("autoName")), "%"
	// + criteriaLowerCase + "%")));
	// pList.add(cb.or(cb.like(cb.lower(r.<String> get("modelName")), "%"
	// + criteriaLowerCase + "%")));
	// pList.add(cb.or(cb.like(cb.lower(r.<String> get("note")), "%"
	// + criteriaLowerCase + "%")));
	// pList.add(cb.or(cb.like(cb.lower(r.<String> get("manCode")), "%"
	// + criteriaLowerCase + "%")));
	// pList.add(cb.or(cb.like(cb.lower(r.<String> get("vin")), "%"
	// + criteriaLowerCase + "%")));
	// pList.add(cb.or(cb.like(cb.lower(r.<String> get("engine")), "%"
	// + criteriaLowerCase + "%")));
	//
	// orPredicate = cb.or(pList.toArray(new Predicate[] {}));
	//
	// }
	//
	// Paginate<Partitem> page = new Paginate<Partitem>();
	// page.setAddPredicate(orPredicate);
	//
	// partItemList = page.paginate(Partitem.class, offset, limit,
	// sortInfo, filterConfig);;
	//
	// return new PartitemPagingLoadResultBean(partItemList, page.count(
	// Partitem.class).intValue(), offset);
	// ;
	//
	// }

	public PartitemLoadResultBean partitemList() {
		PartitemLoadResultBean bean = new PartitemLoadResultBean();
		bean.setData(findAllPartitems());
		return bean;
	}

	@SuppressWarnings("unchecked")
	public List<Auto> findAutos() {
		List<Auto> autoList = null;
		
		try {
			//check cache		
			autoList = (List<Auto>) CacheUtils
					.getCacheData(CacheUtils.AUTO_LIST_KEY);

			if (autoList == null) {
				log.info("get auto list from DB");
				EntityManager mgr = PersistUtils.getEntityManager();
				Query q = mgr.createQuery(
						"select x from Auto x order by name ASC", Auto.class);
				autoList = q.getResultList();
				CacheUtils.setCacheData(CacheUtils.AUTO_LIST_KEY, autoList);
			}
			//			for (Auto auto : autoList) {
//				log.warning("auto:" + auto.getName());
//				String models = "";
//				if (auto.getModels() != null) {
//					for (Model model : auto.getModels()) {
//						models += model.getName() + "[" + model.getId() + "]";
//					}
//				} else {
//					models = "null";
//				}
//				log.warning(models);
//			}
//		} finally {
//			mgr.close();
		} catch (Exception e) {
			log.severe("Failed get auto list");
		}

		return autoList;

	}

	public Partitem findItemByCode(String code) {
		EntityManager mgr = EMF.get().createEntityManager();
		Partitem item = null;
		try {
			TypedQuery<Partitem> q = mgr.createQuery(
					"select x from Partitem x where code = :code",
					Partitem.class);
			q.setParameter("code", code);
			item = q.getSingleResult();
		} finally {
			mgr.close();
		}

		return item;

	}

	public void deletePartitem(Partitem p) {
		if (PersistUtils.isUserManager()) {
			if (p != null) {
				log.warning("remove partitem: " + p.getId());
				PersistUtils.removeObject(p);
			} else {
				log.warning("remove null partitem");
			}
		} else {
			log.severe("unauthorized action: trying to delete partitem");
		}
	}

	public void savePartitem(Partitem p) {
		PersistUtils.mergeObject(p);
	}

	public PartitemPagingLoadResultBean partitemList(int offset, int limit,
			List<SortInfoBean> sortInfo, List<FilterConfigBean> filterConfig) {
		try {

			Paginate<Partitem> page = new Paginate<Partitem>();
			List<Partitem> list = page.paginate(Partitem.class, offset, limit,
					sortInfo, filterConfig);

			return new PartitemPagingLoadResultBean(list, page.count(
					Partitem.class).intValue(), offset);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}

	@SuppressWarnings("unchecked")
	public NewsLoadResultBean lastNews() {
		log.info("loading last news...");
		List<News> newsList = null;
		try {
			newsList = (List<News>) CacheUtils
					.getCacheData(CacheUtils.NEWS_LIST_KEY);
			if (newsList == null) {
				EntityManager mgr = PersistUtils.getEntityManager();
				Query q = mgr.createQuery(
						"select x from News x order by news_date DESC",
						News.class);
				newsList = q.getResultList();
				CacheUtils.setCacheData(CacheUtils.NEWS_LIST_KEY, newsList);
			}
			//		} finally {
//			mgr.close();
		} catch (Exception e) {
			
		}

		NewsLoadResultBean bean = new NewsLoadResultBean();
		bean.setData(newsList);
		return bean;

	}

	public void deleteNews(News p) {
		if (PersistUtils.isUserManager()) {
			if (p != null) {
				log.warning("remove news: " + p.getId());
				PersistUtils.removeObject(p);
				CacheUtils.removeCacheData(CacheUtils.NEWS_LIST_KEY);
			} else {
				log.warning("remove null news");
			}
		} else {
			log.severe("unauthorized action: trying to delete news");
		}
	}

	public void saveNews(News p) {
		if (PersistUtils.isUserManager()) {
			if (p != null) {
				PersistUtils.mergeObject(p);
				CacheUtils.removeCacheData(CacheUtils.NEWS_LIST_KEY);
			}
		} else {
			log.severe("unauthorized action: trying to delete partitem");
		}
	}
	
	public void clearCatalog() {
		if (!GWT.isProdMode() || PersistUtils.isUserManager()) {
			EntityManager mgr = PersistUtils.getEntityManager();
			try {
				Query q = mgr.createQuery("delete from Partitem ");
				q.executeUpdate();

				q = mgr.createQuery("delete from Partgroup");
				q.executeUpdate();

				q = mgr.createQuery("delete from Model");
				q.executeUpdate();

				q = mgr.createQuery("delete from Auto");
				q.executeUpdate();

			} catch (Exception e) {
				log.log(Level.SEVERE, "Failed clear catalog", e);
			} finally {
				CacheUtils.removeAll();
			}
		} else {
			log.severe("unauthorized action: trying to clear catalog");
		}
	}

	public void clearCatalog(Long storeId) {
		if (!GWT.isProdMode() || PersistUtils.isUserManager()) {
			EntityManager mgr = PersistUtils.getEntityManager();
			try {
				Query q = mgr.createQuery(
						"delete from Partitem x where storeId = :storeId");
				q.setParameter("storeId", storeId);
				q.executeUpdate();

			} catch (Exception e) {
				log.log(Level.SEVERE, "Failed clear catalog", e);
			} finally {
				CacheUtils.removeAll();
			}
		} else {
			log.severe("unauthorized action: trying to clear catalog");
		}
	}

}
